﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Valentia.Kinection.DataTypes
{
    /// <summary>
    /// Logger class for all project logging.
    /// </summary>
    public static class Logger
    {
        /// <summary>
        /// Sync. object for log writing.
        /// </summary>
        private static Object _LogSync = new Object();

        /// <summary>
        /// Gets or sets true if loggin is enabled else false.
        /// </summary>
        public static bool LoggingEnabled { get; set; }

        /// <summary>
        /// Gets or sets the log folder. If set empty then will be set to directory of application.
        /// </summary>
        public static String LogFolder { get; set; }

        /// <summary>
        /// Gets or set the application name.
        /// </summary>
        public static String ApplicationName { get; set; }

        /// <summary>
        /// Static constructor
        /// </summary>
        static Logger()
        {
            Logger.LoggingEnabled = true;
            Logger.LogFolder = String.Empty;
            Logger.ApplicationName = String.Empty;
        }

        /// <summary>
        /// Gets the log file full path to write log.
        /// </summary>
        /// <param name="logTime">Time of log.</param>
        /// <returns></returns>
        private static String GetTodayLogFile(DateTime logTime)
        {
            if ((Logger.LogFolder ?? String.Empty).Trim().Length <= 0)
            {
                //Logger.LogFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, String.Format("{0} {1}", Logger.ApplicationName, "Log").Trim());
                Logger.LogFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log");
            }

            if (!Directory.Exists(Logger.LogFolder))
            {
                lock (Logger._LogSync)
                {
                    if (!Directory.Exists(Logger.LogFolder)) { Directory.CreateDirectory(Logger.LogFolder); }
                }
            }

            String innerDirPath = Path.Combine(Logger.LogFolder, logTime.ToString("MM-yyyy"));
            if (!Directory.Exists(innerDirPath))
            {
                lock (Logger._LogSync)
                {
                    if (!Directory.Exists(innerDirPath)) { Directory.CreateDirectory(innerDirPath); }
                }
            }

            //return Path.Combine(innerDirPath, logTime.ToString("dd") + ".log");
            return Path.Combine(innerDirPath, (logTime.ToString("dd") + "-" + Logger.ApplicationName).Trim(' ', '-') + ".log");
        }

        /// <summary>
        /// Writes the log to the file.
        /// </summary>
        /// <param name="logFormat">Log format string.</param>
        /// <param name="args">Argument list.</param>
        public static void Log(String logFormat, params Object[] args) { Logger.Log(null, logFormat, args); }

        /// <summary>
        /// Writes the log to the file.
        /// </summary>
        /// <param name="exp">Excpetion object if any exception to log else null.</param>
        /// <param name="logFormat">Log format string.</param>
        /// <param name="args">Argument list.</param>
        public static void Log(Exception exp, String logFormat, params Object[] args)
        {
            try
            {
                if (!Logger.LoggingEnabled) return;

                DateTime logTime = DateTime.Now;

                String logText = logTime.ToString("HH:mm:ss.fff") + "--> " + String.Format(logFormat, args) + Environment.NewLine;

                int expLevel = 0;
                while (exp != null)
                {
                    logText += "--------------------" + exp.GetType().FullName + "--------------------" + Environment.NewLine;
                    if (expLevel > 0) { logText += "Inner exception level >> " + expLevel.ToString() + Environment.NewLine; }
                    logText += exp.Message + Environment.NewLine;
                    logText += exp.StackTrace + Environment.NewLine;
                    logText += "------------------------------------------------------------" + Environment.NewLine;

                    exp = exp.InnerException;
                    expLevel++;
                }

                File.AppendAllText(Logger.GetTodayLogFile(logTime), logText);
            }
            catch { }
        }
    }
}
